package com.siashan.toolkit.oss.aws.core;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.amazonaws.util.IOUtils;
import com.siashan.toolkit.oss.core.OssResult;
import com.siashan.toolkit.oss.core.OssStorageService;
import com.siashan.toolkit.oss.core.enums.OssChannel;
import com.siashan.toolkit.oss.core.exception.ToolkitOssException;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
 * AWS  S3 存储
 *
 * @author siashan
 * @date  2025/6/5 11:47
 */
public class AwsS3StorageService extends OssStorageService {
    /**
     * AWS S3 客户端
     */
    private AmazonS3 amazonS3;
    /**
     * 阿里云OSS配置
     */
    private AwsS3Config config;


    /**
     * 默认构造方法
     *
     * 初始化S3配置
     */
    public AwsS3StorageService() {
        config = new AwsS3Config();
        config.setAccessKeyId(AwsS3Configuration.getAccessKeyId());
        config.setAccessKeySecret(AwsS3Configuration.getAccessKeySecret());
        config.setBucketName(AwsS3Configuration.getBucketName());
        config.setDomain(AwsS3Configuration.getDomain());
        config.setEndPoint(AwsS3Configuration.getEndPoint());
        config.setPrefix(AwsS3Configuration.getPrefix());
        init();
    }

    /**
     * 构造方法
     *
     * @param config  S3配置
     */
    public AwsS3StorageService(AwsS3Config config) {
        this.config = config;
        init();
    }

    /**
     * 初始化S3客户端
     */
    private void init() {
        System.setProperty("com.amazonaws.sdk.disableCertChecking", "true");
        ClientConfiguration clientConfiguration = new ClientConfiguration();//初始化客户端config
        clientConfiguration.setMaxConnections(this.config.getMaxConnections());
        clientConfiguration.setProtocol(Protocol.HTTPS);//设置mos 请求协议为http
        clientConfiguration.setSignerOverride("S3SignerType");
        AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
                this.config.getEndPoint(), this.config.getRegion());//创建AWS凭证
        AWSCredentials awsCredentials = new BasicAWSCredentials(this.config.getAccessKeyId(),
                this.config.getAccessKeySecret());
        AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
        this.amazonS3 = AmazonS3Client.builder().withEndpointConfiguration(endpointConfiguration)
                .withClientConfiguration(clientConfiguration).withCredentials(awsCredentialsProvider)
                .disableChunkedEncoding().withPathStyleAccessEnabled(this.config.getPathStyleAccess()).build();
    }

    /**
     * 文件上传
     *
     * @param data    文件字节数组
     * @param path    文件路径，包含文件名
     * @return Oss上传结果
     */
    @Override
    public OssResult upload(byte[] data, String path) {
        return upload(new ByteArrayInputStream(data), path);
    }

    /**
     * 文件上传
     *
     * @param inputStream   字节流
     * @param path          文件路径，包含文件名
     * @return   Oss上传结果
     */
    @Override
    public OssResult upload(InputStream inputStream, String path) {
        try {
            putObject(this.config.getBucketName(), path, inputStream,inputStream.available(),"application/octet-stream");
        } catch (Exception e) {
            throw new ToolkitOssException("上传文件失败，请检查配置信息", e);
        }

        return OssResult.build(path,config.getDomain(), OssChannel.ALIYUN);
    }

    /**
     * 文件上传
     *
     * @param data     文件字节数组
     * @param suffix   文件后缀  eg: .gif .txt .png
     * @return  Oss上传结果
     */
    @Override
    public OssResult uploadSuffix(byte[] data, String suffix) {
        return upload(data, getPath(config.getPrefix(), suffix));
    }

    /**
     * 文件上传
     *
     * @param inputStream  字节流
     * @param suffix       后缀
     * @return  Oss上传结果
     */
    @Override
    public OssResult uploadSuffix(InputStream inputStream, String suffix) {
        return upload(inputStream, getPath(config.getPrefix(), suffix));
    }

    /**
     * 文件删除
     *
     * @param fileName  资源名称
     * @return 是否成功标识
     * @since 1.0.2
     */
    @Override
    public boolean remove(String fileName) {
        amazonS3.deleteObject(this.config.getBucketName(), fileName);
        return true;
    }



    /**
     * 上传文件
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param stream 文件流
     * @param size 大小
     * @param contextType 类型
     * @throws Exception
     * @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObject">AWS
     * API Documentation</a>
     */
    public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
                                     String contextType) throws Exception {
        byte[] bytes = IOUtils.toByteArray(stream);
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(size);
        objectMetadata.setContentType(contextType);
        objectMetadata.setHeader("x-amz-acl", "public-read");
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        // 上传
        return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);

    }

}
